package com.maybach.component.city;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.maybach.component.city.constants.AreaTypeEnum;
import com.maybach.component.city.domain.Area;
import com.maybach.component.city.domain.City;
import com.maybach.component.city.domain.Province;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.*;

/**
 * Created by well on 15/3/26.
 */
public class CityData {

    private static List<Province> provinceList = Collections.emptyList();

    private static List<City> cityList = Collections.emptyList();

    private static Map<Integer, List<City>> map;

    private static List<Area> areaList = Collections.emptyList();

    private static Map<Integer, List<Province>> proMap;

    private static String[] excludeCity = new String[]{"杭州市"};

    public static String defaultCityId = "999";


    static {
        try {
            InputStream resourceAsStream = CityData.class.getClassLoader().getResourceAsStream("data/province.json");
            int buffSize = 1024;
            ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);
            byte[] temp = new byte[buffSize];
            int size;
            while ((size = resourceAsStream.read(temp)) != -1) {
                out.write(temp, 0, size);
            }
            resourceAsStream.close();

            byte[] content = out.toByteArray();
            provinceList = JSON.parseArray(new String(content, Charset.forName("UTF-8")), Province.class);
            out.close();
            Collections.sort(provinceList, new Comparator<Province>() {
                @Override
                public int compare(Province o1, Province o2) {
                    return o1.getProSort() - o2.getProSort();
                }
            });

            resourceAsStream = CityData.class.getClassLoader().getResourceAsStream("data/city.json");
            out = new ByteArrayOutputStream(buffSize);
            temp = new byte[buffSize];
            size = 0;
            while ((size = resourceAsStream.read(temp)) != -1) {
                out.write(temp, 0, size);
            }
            resourceAsStream.close();

            content = out.toByteArray();
            cityList = JSON.parseArray(new String(content,Charset.forName("UTF-8")), City.class);
            out.close();
            Collections.sort(cityList, new Comparator<City>() {
                @Override
                public int compare(City o1, City o2) {
                    return o1.getCitySort() - o2.getCitySort();
                }
            });

            resourceAsStream = CityData.class.getClassLoader().getResourceAsStream("data/area.json");
            out = new ByteArrayOutputStream(buffSize);
            temp = new byte[buffSize];
            size = 0;
            while ((size = resourceAsStream.read(temp)) != -1) {
                out.write(temp, 0, size);
            }
            resourceAsStream.close();

            content = out.toByteArray();
            areaList = JSON.parseArray(new String(content,Charset.forName("UTF-8")), Area.class);
            out.close();
            Collections.sort(areaList, new Comparator<Area>() {
                @Override
                public int compare(Area o1, Area o2) {
                    return o1.getAreaSort() - o2.getAreaSort();
                }
            });

            proMap = new HashMap<Integer, List<Province>>(areaList.size() * 2);
            for (Area area : areaList) {
                List<Province> provinceList1 = new ArrayList<Province>();
                for (Province province : provinceList) {
                    if (area.getAreaId().intValue() == province.getAreaId().intValue()) {
                        provinceList1.add(province);
                    }
                }
                proMap.put(area.getAreaId(), provinceList1);
            }


            map = new HashMap<Integer, List<City>>(provinceList.size() * 2);
            for (Province p : provinceList) {
                List<City> cityList1 = new ArrayList<City>();
                for (City c : cityList) {
                    if (c.getProID().intValue() == p.getProID().intValue()) {
                        cityList1.add(c);
                    }
                }
                map.put(p.getProID(), cityList1);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static boolean exclude(City c) {
        for (String s : excludeCity) {
            if (s.equals(c.getName())) {
                return true;
            }
        }
        return false;
    }


    //获取省份下的城市
    public static List<City> getCity(Integer proId) {
        List<City> list = map.get(proId);
        if (CollectionUtils.isNotEmpty(list)) {
            return Lists.newArrayList(list);
        }
        return Lists.newArrayList();
    }

    public static List<City> getCityList() {
        return Lists.newArrayList(cityList);
    }

    public static List<Province> getProvince() {
        return Lists.newArrayList(provinceList);
    }

    //大区列表
    public static List<Area> getAreaList() {
        return Lists.newArrayList(areaList);
    }

    //获取大区下的省份
    public static List<Province> getProvinceByAreaId(Integer areaId) {
        List<Province> list = proMap.get(areaId);
        if (CollectionUtils.isNotEmpty(list)) {
            return Lists.newArrayList(list);
        }
        return Lists.newArrayList();
    }

    public static String getCityCn(Integer province, Integer city) {
        if (province == null || city == null) {
            return null;
        }
        return provinceCn(province) + cityCn(province, city);

    }

    public static String provinceCn(Integer province) {
        if (province == null) {
            return "";
        }
        List<Province> province1 = getProvince();
        for (Province p : province1) {
            if (p.getProID().intValue() == province.intValue()) {
                return p.getName();
            }
        }
        return "";
    }

    public static Integer provinceIdByCn(String province) {
        if (province == null) {
            return null;
        }
        List<Province> province1 = getProvince();
        for (Province p : province1) {
            if (p.getName().equals(province)) {
                return p.getProID();
            }
        }
        return null;
    }

    public static String cityCn(Integer province, Integer city) {
        if (province == null || city == null) {
            return "";
        }
        List<City> list = getCity(province);
        if (list == null) {
            return "";
        }
        for (City c : list) {
            if (c.getCityId().intValue() == city.intValue()) {
                return c.getName();
            }
        }
        return "";
    }

    public static String areaNameById(Integer areaId) {
        if (areaId == null) {
            return "";
        }
        List<Area> list = getAreaList();
        if (list == null) {
            return "";
        }
        for (Area area : list) {
            if (area.getAreaId().intValue() == areaId.intValue()) {
                return area.getName();
            }
        }
        return "";
    }

    public static String cityNameById(Integer cityId) {
        if (cityId == null) {
            return "";
        }
        List<City> list = getCityList();
        if (list == null) {
            return "";
        }
        for (City city : list) {
            if (city.getCityId().intValue() == cityId.intValue()) {
                return city.getName();
            }
        }
        return "";
    }

    //区域名称
    public static String areaNameByTypeId(Integer areaType, Integer areaId) {
        String areaName = "";
        if (areaType == null || areaId == null) {
            return areaName;
        }
        if (AreaTypeEnum.Area.getStatus().intValue() == areaType.intValue()) {
            areaName = areaNameById(areaId);
        } else if (AreaTypeEnum.Province.getStatus().intValue() == areaType.intValue()) {
            areaName = provinceCn(areaId);
        } else if (AreaTypeEnum.City.getStatus().intValue() == areaType.intValue()) {
            areaName = cityNameById(areaId);
        }
        return areaName;
    }

    //proId获取Province
    public static Province getProvinceById(Integer proId) {
        if (proId == null) {
            return null;
        }
        List<Province> province1 = getProvince();
        if (province1 == null) {
            return null;
        }
        for (Province p : province1) {
            if (p.getProID().intValue() == proId.intValue()) {
                return p;
            }
        }
        return null;
    }

    //proId获取Province
    public static City getCityById(Integer cityId) {
        if (cityId == null) {
            return null;
        }
        List<City> list = getCityList();
        if (list == null) {
            return null;
        }
        for (City city : list) {
            if (city.getCityId().intValue() == cityId.intValue()) {
                return city;
            }
        }
        return null;
    }

    //区域名称
    public static String allName(Integer areaType, Integer areaId) {
        String areaName = "";
        if (areaType == null || areaId == null) {
            return areaName;
        }
        if (AreaTypeEnum.Area.getStatus().intValue() == areaType.intValue()) {
            areaName = areaNameById(areaId);
        } else if (AreaTypeEnum.Province.getStatus().intValue() == areaType.intValue()) {
            Province pro = getProvinceById(areaId);
            String area = areaNameById(pro.getAreaId());
            areaName = area + "-" + pro.getName();
        } else if (AreaTypeEnum.City.getStatus().intValue() == areaType.intValue()) {
            City city = getCityById(areaId);
            Province pro = getProvinceById(city.getProID());
            String area = areaNameById(pro.getAreaId());
            areaName = area + "-" + pro.getName() + "-" + city.getName();
        }
        return areaName;
    }

    /**
     * 根据区域获取支持的省份。
     *
     * @param area 可以为大区、省份或市
     * @return
     */
    public static List<Province> getProvinces(String area) {
        if (StringUtils.equals(area, "全国")) {
            return getProvince();
        }
        for (Area a : areaList) {
            if (StringUtils.equals(a.getName(), area)) {
                List<Province> provinces = Lists.newArrayList();
                for (Province province : provinceList) {
                    if (province.getAreaId() != null && province.getAreaId().equals(a.getAreaId())) {
                        provinces.add(province);
                    }
                }
                return provinces;
            }
        }
        for (Province province : provinceList) {
            if (StringUtils.equals(province.getName(), area)) {
                return Lists.newArrayList(province);
            }
        }
        for (City city : cityList) {
            if (StringUtils.equals(city.getName(), area)) {
                for (Province province : provinceList) {
                    if (province.getProID() != null && province.getProID().equals(city.getProID())) {
                        return Lists.newArrayList(province);
                    }
                }
            }
        }
        return null;
    }

    /**
     * 根据区域获取支持的城市。
     *
     * @param area         可以为大区、省份或市
     * @param provinceName 省份
     * @return
     */
    public static List<City> getCities(String area, String provinceName) {
        Integer provinceId = null;
        for (Province province : provinceList) {
            if (StringUtils.equals(province.getName(), provinceName)) {
                provinceId = province.getProID();
                break;
            }
        }
        if (provinceId == null) {
            return null;
        }
        if (StringUtils.isBlank(area)) {
            area = "全国";
        }
        if (StringUtils.equals(area, "全国")) {
            return getCitiesFromProvinceId(provinceId, provinceName);
        }

        for (Area a : areaList) {
            if (StringUtils.equals(a.getName(), area)) {
                for (Province province : provinceList) {
                    if (province.getAreaId() != null && province.getAreaId().equals(a.getAreaId())
                            && province.getProID() != null && province.getProID().equals(provinceId)) {
                        return getCitiesFromProvinceId(provinceId, province.getName());
                    }
                }
                return null;
            }
        }
        for (Province province : provinceList) {
            if (StringUtils.equals(province.getName(), area)
                    && province.getProID() != null && province.getProID().equals(provinceId)) {
                return getCitiesFromProvinceId(provinceId, province.getName());
            }
        }
        for (City city : cityList) {
            if (StringUtils.equals(city.getName(), area)) {
                if (provinceId.equals(city.getProID())) {
                    return Lists.newArrayList(city);
                }
            }
        }
        return null;
    }

    /**
     * 根据区域获取支持的城市。
     *
     * @param area 可以为大区、省份或市
     * @return
     */
    public static List<City> getCities(String area) {
        if (StringUtils.equals(area, "全国")) {
            return getCityList();
        }
        List<City> list = Lists.newArrayList();
        for (Area a : areaList) {
            if (StringUtils.equals(a.getName(), area)) {
                for (Province province : provinceList) {
                    if (province.getAreaId() != null && province.getAreaId().equals(a.getAreaId())) {
                        List<City> list1 = getCitiesFromProvinceId(province.getProID(), province.getName());
                        if (CollectionUtils.isNotEmpty(list1)) {
                            list.addAll(list1);
                        }
                    }
                }
            }
        }
        if (CollectionUtils.isNotEmpty(list)) {
            return list;
        }
        for (Province province : provinceList) {
            if (StringUtils.equals(province.getName(), area)) {
                List<City> list1 = getCitiesFromProvinceId(province.getProID(), province.getName());
                if (CollectionUtils.isNotEmpty(list1)) {
                    return list1;
                }
            }
        }
        for (City city : cityList) {
            if (StringUtils.equals(city.getName(), area)) {
                return Lists.newArrayList(city);
            }
        }
        return null;
    }

    /**
     * 根据区域名称获取城市列表
     *
     * @param area
     * @return
     */
    public static List<Province> getProvinceByAreaName(String area) {
        List<Province> list = Lists.newArrayList();
        for (Area a : areaList) {
            if (StringUtils.equals(a.getName(), area)) {
                for (Province province : provinceList) {
                    if (province.getAreaId() != null && province.getAreaId().equals(a.getAreaId())) {
                        list.add(province);
                    }
                }
            }
        }
        return list;
    }

    /**
     * 根据省份名称获取城市列表
     *
     * @param province
     * @return
     */
    public static List<City> getCityByProvinceName(String province) {
        List<City> list = Lists.newArrayList();
        for (Province a : provinceList) {
            if (StringUtils.equals(a.getName(), province)) {
                for (City city : cityList) {
                    if (city.getProID() != null && city.getProID().equals(a.getProID())) {
                        list.add(city);
                    }
                }
            }
        }
        return list;
    }
//    /**
//     * 根据区域名称获取以下的城市
//     * @param area
//     * @return
//     */
//    public static List<City> getCitys(String area){
//        if (StringUtils.equals(area, "全国")) {
//            City city = new City();
//            city.setName("全国");
//            List<City> list = new ArrayList<City>();
//            list.add(city);
//            return list;
//        }
//        return getCities(area);
//    }


    /**
     * 根据provinceId获取所在城市，兼容直辖市。
     *
     * @param provinceId
     * @return
     */
    private static List<City> getCitiesFromProvinceId(Integer provinceId, String provinceName) {
        if (provinceId == null) {
            return null;
        }
        List<City> cities = getCity(provinceId);
        if (CollectionUtils.isNotEmpty(cities)) {
            return cities;
        }
        List<City> cityList2 = Lists.newArrayList();
        City city = new City();
        city.setName(provinceName);
        cityList2.add(city);
        return cityList2;
    }

    //根据名称获取Province
    public static Province getProvinceByStr(String proName) {
        if (StringUtils.isEmpty(proName)) {
            return null;
        }
        List<Province> province1 = getProvince();
        if (province1 == null) {
            return null;
        }
        for (Province p : province1) {
            if (StringUtils.equals(p.getName(), proName)) {
                return p;
            }
        }
        return null;
    }


    public static City getCityByStr(String cityName) {
        if (StringUtils.isEmpty(cityName)) {
            return null;
        }
        List<City> list = getCityList();
        if (list == null) {
            return null;
        }
        for (City c : list) {
            if (StringUtils.equals(c.getName(), cityName)) {
                return c;
            }
        }
        return null;
    }


    //获取区域
    public static Area getAreaById(Integer areaId) {
        if (areaId == null) {
            return null;
        }
        List<Area> list = getAreaList();
        if (list == null) {
            return null;
        }
        for (Area area : list) {
            if (area.getAreaId().intValue() == areaId.intValue()) {
                return area;
            }
        }
        return null;
    }

    public static Map getProvinceByArea() {
        Map m = new HashMap();
        List<Area> areaList = getAreaList();
        for (Area area : areaList) {
            if (area.getAreaId().equals(1)) {
                continue;
            }
            Map<String, Object> data = new HashMap();
            data.put("area", area);
            data.put("provinceList", getProvinceByAreaId(area.getAreaId()));


            m.put(area.getAreaId(), data);
        }
        return m;
    }

}
